package libra;

import java.util.List;
import java.util.Properties;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.FileWritableDataSource;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.transport.util.WritableDataSourceRegistry;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;

@Component
public class InitWrite {
	@Value("${spring.cloud.sentinel.datasource.load-rule-nacos.nacos.server-addr}")
	private String nacosAddr;
	@Value("${spring.cloud.sentinel.datasource.load-rule-nacos.nacos.dataId}")
	private String dataId;
	@Value("${spring.cloud.sentinel.datasource.load-rule-file.file.file}")
	private String filePath;
	
	@PostConstruct
	public void initWrite() {
		/*
		 * 方式一、基于原生WritableDataSource接口实现规则持久化(通用方式)
		 */
		WritableDataSource<List<FlowRule>> nacosRuleWDS = new WritableDataSource<List<FlowRule>>() {
			// 实现WritableDataSource接口的write()方法，传入值为此时更新规则的规则集合
			@Override
			public void write(List<FlowRule> value) throws Exception {
				// 创建一个properties文件，并配置Nacos的服务地址
				Properties prop = new Properties();
				// 如果是nacos单机，直接传入ip地址 如果是nacos集群，可配置多个IP地址，使用','号隔开
				prop.put(PropertyKeyConst.SERVER_ADDR, nacosAddr);
				// 通过传入的properties配置文件，创建一个ConfigService配置中心服务
				ConfigService configService = NacosFactory.createConfigService(prop);
				configService.publishConfig(dataId, "DEFAULT_GROUP", JSONObject.toJSONString(value));
				configService.shutDown();
			}
			@Override
			public void close() throws Exception {}
		};
		/*
		 * 将写数据源通过WritableDataSourceRegistry进行注册。
		 * 收到控制台推送的规则更新时，Sentinel会先更新到内存规则，然后调用自定义实现WritableDataSource将更新规则集合传入进行持久化。
		 */
		WritableDataSourceRegistry.registerFlowDataSource(nacosRuleWDS);


		/*
		 * 方式二、基于WritableDataSource接口的子实现FileWritableDataSource进行规则持久化(仅适用于File)
		 */
		// 如果不实现WritableDataSource接口并进行注册，则底层仅会对新的规则进行更新，而不会持久化到本地
		Converter<List<DegradeRule>, String> converter = new Converter<List<DegradeRule>, String>() {
			@Override
			public String convert(List<DegradeRule> source) {
				System.out.println("写入：" + source);
				return JSONObject.toJSONString(source);
			}
		};
		WritableDataSource<List<DegradeRule>> fileRuleWDS = new FileWritableDataSource<>(filePath, converter);		
		/*
		 * 将写数据源通过WritableDataSourceRegistry进行注册。
		 * 收到控制台推送的规则更新时，Sentinel会先更新到内存规则，然后调用自定义实现WritableDataSource将更新规则集合传入进行持久化。
		 */
		WritableDataSourceRegistry.registerDegradeDataSource(fileRuleWDS);
	}
}
